/*
 * lista.c
 *
 *  Created on: 20/10/2011
 *      Author: Pablo Arias & Juan Pablo De Blas
 */

#include <stdlib.h>
#include <semaphore.h>

#include "lista.h"

extern int tamanioCache;
extern struct TDD_entry *TDD;
extern pthread_mutex_t 	mutexTDD;


void add_int(Nodo **lst, int valor){
   Nodo *aux;
   Nodo *nuevo=(Nodo*)malloc(sizeof(Nodo));

   nuevo->info=valor;
   nuevo->sig=NULL;

   if( *lst == NULL ){
      *lst = nuevo;
   }
   else{
      aux = *lst;
      while( aux->sig != NULL )
      {
         aux = aux->sig;
      }

      aux->sig = nuevo;
   }
}

void add_uint(uNodo **lst, unsigned int valor){
   uNodo *aux;
   uNodo *nuevo=(uNodo*)malloc(sizeof(uNodo));

   nuevo->info=valor;
   nuevo->sig=NULL;

   if( *lst == NULL ){
      *lst = nuevo;
   }
   else{
      aux = *lst;
      while( aux->sig != NULL )
      {
         aux = aux->sig;
      }

      aux->sig = nuevo;
   }
}

void printList_int(Nodo *lst){
	Nodo *aux;
	aux = lst;

	while(aux != NULL){
		printf("%d \n",aux->info);
		aux = aux->sig;
	}
}

int unqueue(Nodo **lst){

	int valor;

	Nodo *aux;

	aux= *lst;
	valor = aux->info;
	*lst=aux->sig;

	free(aux);
	return valor;
}

unsigned int unqueue_u(uNodo **lst){

	unsigned int valor;

	uNodo *aux;

	aux= *lst;
	valor = aux->info;
	*lst=aux->sig;

	free(aux);
	return valor;
}

void agregarEntradaTDD(const char *path){

	struct TDD_entry *newArch;

	newArch = (struct TDD_entry*) malloc (sizeof(struct TDD_entry));
	newArch->path = (char*) malloc(strlen(path) + 1);

	strncpy(newArch->path, path, strlen(path) + 1);
	newArch->cache = NULL;
	newArch->cantSecEnCache = (tamanioCache * 1024)/512;
	pthread_mutex_init(&newArch->mutexCache, NULL);
	newArch->siguiente = NULL;

	insertarEnTDD(&TDD, newArch);
}

void insertarEnTDD(struct TDD_entry **TDD, struct TDD_entry *newArch){

	struct t_pedido *aux, *ant;
	int 			retval;

	pthread_mutex_lock(&mutexTDD);

	/* inserto adelante */
	newArch->siguiente = *TDD;
	*TDD = newArch;

	pthread_mutex_unlock(&mutexTDD);
}

struct TDD_entry *buscarEnTDD(const char *path, struct TDD_entry *ant) {

	struct TDD_entry *aux;

	aux = TDD;
	ant = NULL;
	TDD=1;
	pthread_mutex_lock(&mutexTDD);

	while((aux != NULL) && (strcmp(aux->path, path) != 0))
	{
		ant = aux;
		aux = aux->siguiente;
	}

	pthread_mutex_lock(&mutexTDD);

	/* si no encuentro el path en TDD */
	if(aux == NULL)
	{
		ant = NULL;
		return NULL;
	}
	else /* si encuentro el path en la TDD */
	{
		return aux;
	}
}

void liberarNodoPath(struct TDD_entry **TDD, struct TDD_entry *nodoAnterior)
{
	struct TDD_entry 	*pathLiberar;
	struct t_cache		*secLiberar;

	pthread_mutex_lock(&mutexTDD);

	if(nodoAnterior == NULL)
	{
		pathLiberar = *TDD;
		*TDD = (*TDD)->siguiente;
	}
	else
	{
		pathLiberar = nodoAnterior->siguiente;
		nodoAnterior->siguiente = pathLiberar->siguiente;
	}

	while(pathLiberar->cache != NULL)
	{
		secLiberar = pathLiberar->cache;
		pathLiberar->cache = secLiberar->siguiente;

		/* depende de si le hago malloc al buffer
		 * free(secLiberar->buffer); */

		free(secLiberar);
	}

	/* liberamos la memoria y destruimos mutex */
	pthread_mutex_destroy(&pathLiberar->mutexCache);
	free(pathLiberar->path);
	free(pathLiberar);

	pthread_mutex_unlock(&mutexTDD);
}

void clearTDD(void)
{
	while(TDD != NULL)
	{
		liberarNodoPath(&TDD, NULL);
	}
}
